#pragma once
#include"detail.hpp"
#include"abstract.hpp"
#include"field.hpp"
#include<vector>

namespace RPC_project
{
    typedef std::pair<std::string  ,int>  Address;

    class JsonMessage :public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
        virtual std::string Serialize() override
        {
            std::string body;
            bool ret = jsonTool::serialize(_body,body);
            if(ret == false)
            {
                return std::string();
            }
            else
            {
                return body;
            }
        }
        
        virtual bool Deserialize(const std::string &msg) override // 反序列化,将其中的数据设置进成员变量
        {
            return jsonTool::Deserialize(msg, _body);
        }

        virtual bool Check() =0;//每一种消息检验方法不同，子类实现 // 检验消息是否完整

    protected:
        Json::Value _body;
    };


    class JsonRequest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };
    
    class JsonResponse : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonResponse>;

        virtual bool Check() override //检测rcode是否存在 ,检验格式是否正确
        {
            //在响应中，⼤部分的响应都只有响应状态码 
            //因此只需要判断响应状态码字段是否存在，类型是否正确即可 
            if(_body[KEY_RCODE].isNull() == true)//不存在
            {
                ELOG("响应中没有响应状态码");
                return false;
            }
            if(_body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码类型错误");
                return false;
            }
            return true;
        }

        virtual RCode Rcode()
        {
            return (RCode)_body[KEY_RCODE].asInt();
        }
        virtual void SetRcode( RCode rcode)
        {
            _body[KEY_RCODE] = int(rcode);
        }
    };


/////////////////////////////////////三种具体request
    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;
        virtual bool Check() override
        {//RPCrequset中，包含请求的方法名称（字符串） ，参数（对象） 
            if(_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)//不存在
            {
                ELOG("RPC请求中没有方法类型或者方法名称类型错误");
                return false;
            }
            if(_body[KEY_PARAMS].isNull() == true || _body[KEY_PARAMS].isObject() == false)
            {
                ELOG("RPC请求中没有参数类型或者参数类型错误");
                return false;
            }
            return true;
        }

        std::string Method()
        {
            return _body[KEY_METHOD].asString();

        }
        void SetMethod(const std::string &method_name)
        {
            _body[KEY_METHOD]=method_name;
        }


        Json::Value Params()
        {
            return _body[KEY_PARAMS];

        }
        void SetParams(const Json::Value & params )
        {
            _body[KEY_PARAMS] = params;
            Json::FastWriter writer;
            std::cout << "加入参数"<< std::endl;
            std::cout << writer.write(_body) << std::endl;
        }
    };


    class TopicRequest : public JsonRequest
    {
    public:
    
        using ptr = std::shared_ptr<TopicRequest>;

        virtual bool Check() override
        {//TopicRequest中，包含请求的主题名称 ，操作类型 ， 
            if(_body[KEY_TOPIC_KEY].isNull() == true || _body[KEY_TOPIC_KEY].isString() == false)//不存在
            {
                ELOG("Topic请求中没有主题名称类型或者主题名称类型错误");
                return false;
            }
            if(_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isIntegral() == false)//不存在
            {
                ELOG("Topic请求中没有操作类型名称类型或者操作类型错误");
                return false;
            }
            if((_body[KEY_OPTYPE].asInt() ==  (int)TopicOptype ::TOPIC_PUBLISH) &&
                (_body[KEY_TOPIC_MSG].isNull() == true 
                || _body[KEY_TOPIC_MSG].isString() == false))
            {

                ELOG("Topic请求中的publish中 ，没有消息或者消息字段类型错误");
                return false;
            }

            return true;
        }

        std::string TopickKey()
        {
            return _body[KEY_TOPIC_KEY].asString();

        }
        void SetTopickKey(const std::string &key)
        {
            _body[KEY_TOPIC_KEY] = key;
        }

        TopicOptype OpType()
        {
            return  (TopicOptype)_body[KEY_OPTYPE].asInt();
        }
        void SetOpType(const TopicOptype &optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        std::string TopickMsg()
        {
            return _body[KEY_TOPIC_MSG].asString();

        }
        void SetTopickMsg(const std::string &msg)
        {
            _body[KEY_TOPIC_MSG] = msg;
        }


    };


    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        virtual bool Check() override
        {//ServiceRequest中，包含请求的 方法名称
            if(_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)//不存在
            {
                ELOG("Service请求中没有方法名称类型或者方法名称类型错误");
                return false;
            }

            if(_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isIntegral() == false)//不存在
            {
                ELOG("Service请求中没有操作类型名称类型或者操作类型错误");
                return false;
            }

            //发现服务请求中没有host ，其它服务没有host
            if((_body[KEY_OPTYPE].asInt() != (int)(ServiceOptype::SERVICE_DISCOVERY) )&&
            (_body[KEY_HOST].isNull() == true||
                _body[KEY_HOST].isObject() ==false ||
                _body[KEY_HOST][KEY_HOST_IP].isNull() == true ||
                _body[KEY_HOST][KEY_HOST_IP].isString() == false||
                _body[KEY_HOST][KEY_HOST_PORT].isNull() == true ||
                _body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false))
            {

                ELOG("Service请求的非发现请求中主题地址信息错误");
                return false;
            }

            return true;
        }

        std::string Method()
        {
            return _body[KEY_METHOD].asString();

        }
        void SetMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }

        ServiceOptype  OpType()
        {
            return  (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }
        void SetOpType(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        Address Host()
        {
            Address addr;
            addr.first =_body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void SetHost(const Address &addr)
        {
            Json::Value val;
            val[KEY_HOST_IP] = addr.first;
            val[KEY_HOST_PORT] = addr.second;
            _body[KEY_HOST] =val;
        }


    };


/////////////////////////////////////三种具体response
    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        
        virtual bool Check() override
        {
            if(_body[KEY_RCODE].isNull() == true ||
                _body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应中没有响应状态码或响应状态码类型错误");
                return false;
            }
             if(_body[KEY_RESULT].isNull() == true)
            {
                ELOG("响应中没有Rpc调用结果或结果类型错误");
                return false;
            }
            return true;
        }

        Json::Value Result()
        {
            return _body[KEY_RESULT];
        }
        void SetResult(const Json::Value &value)
        {
            _body[KEY_RESULT]=value;
        }
    };

    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
    
    };

    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;
        
        virtual bool Check() override
        {
            if(_body[KEY_RCODE].isNull() == true ||
                _body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应中没有响应状态码或响应状态码类型错误");
                return false;
            }

            if(_body[KEY_OPTYPE].isNull() == true ||
                _body[KEY_OPTYPE].isInt() == false)
            {
                ELOG("响应中没有服务操作类型 或 服务操作类型错误");
                return false;
            }
            //服务发现  
            //KEY_METHOD 用于判断两种不同的服务响应  1.上线下线注册   2.发现
            if(_body[KEY_OPTYPE].asInt() ==  (int)ServiceOptype:: SERVICE_DISCOVERY&&
                (_body[KEY_METHOD].isNull() ==true || 
                 _body[KEY_METHOD].isString() == false ||
                 _body[KEY_HOST].isNull() ==true || 
                 _body[KEY_HOST].isArray() == false ))
            {
                ELOG("响应为服务发现服务响应 ，但该响应中信息错误");
                return false;
            }
            return true;
        }

        ServiceOptype  OpType()
        {
            return  (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }
        void SetOpType(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        std::string Method()
        {
            return _body[KEY_METHOD].asString();
        }
        void SerMethod(const std::string & method)
        {
            _body[KEY_METHOD] = method;
        }

        void SetHost(std::vector<Address> addrs)
        {
            for(auto& it :addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP] = it.first;
                val[KEY_HOST_PORT] = it.second;
                _body[KEY_HOST].append(val);
            }
        }
        std::vector<Address> Hosts()
        {
            std::vector<Address> hosts;
            int sz=_body[KEY_HOST].size();
            for(int i=0 ;i<sz;i++)
            {
                Address addr;
                addr.first=_body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second=_body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                hosts.push_back(addr);
            }
            return hosts;
        }

    };

    //实现一个消息对象的生产工厂
    //把不同对象的生产全部集中到一起
    //将new的过程集中起来
    class MessageFactory
    {
    public: 
        static BaseMessage::ptr Create(MType type)
        {
            switch(type)
            {
                case MType::REQ_RPC : return std::make_shared<RpcRequest>();
                case MType::REQ_SERVICE : return std::make_shared<ServiceRequest>();
                case MType::REQ_TOPIC : return std::make_shared<TopicRequest>();
                case MType::RSP_RPC : return std::make_shared<RpcResponse>();
                case MType::RSP_SERVICE: return std::make_shared<ServiceResponse>();
                case MType::RSP_TOPIC : return std::make_shared<TopicResponse>();

            }
            //对不上返回nullptr
            return BaseMessage::ptr();
            
        }

    };
    
}

